#include "threadpool.h"

int exitPipe[2];

void sighandler(int signum)
{
    printf("sig %d is coming.\n", signum);
    //往管道中写入一个1
    int one = 1;
    write(exitPipe[1], &one, sizeof(one));
}

int main(int argc, char ** argv)
{   //ip port threadNum
    ARGS_CHECK(4, argc);

    //创建退出的管道,位于父子进程间,在fork之前
    pipe(exitPipe);
    pid_t pid = fork();
    
    if(pid > 0) {//父进程的执行流程
        signal(SIGUSR1, sighandler);//只有父进程处理10号信号
        close(exitPipe[0]);//父进程关闭管道的读端
        wait(NULL);
        printf("parent process is exiting.\n");
        exit(0);
    }

    close(exitPipe[1]);//子进程关闭管道的写端
    //子进程的执行流程

    threadpool_t threadpool;
    //初始化线程池
    threadpoolInit(&threadpool, atoi(argv[3]));

    //启动线程池
    threadpoolStart(&threadpool);

    //创建服务器的监听套接字
    int listenfd = tcpInit(argv[1], atoi(argv[2]));

    //创建epoll的实例
    int epfd = epoll_create1(0);
    ERROR_CHECK(epfd, -1, "epoll_create1");

    //epoll监听listenfd的读事件
    epollAddReadEvent(epfd, listenfd);
    //epoll监听exitPipe[0]的读事件
    epollAddReadEvent(epfd, exitPipe[0]);

    struct epoll_event eventArr[100] = {0};

    int nready = 0;
    while(1) {
        nready = epoll_wait(epfd, eventArr, 100, -1);

        for(int i = 0; i < nready; ++i) {
            int fd = eventArr[i].data.fd;
            if(fd == listenfd) {
                struct sockaddr_in clientAddr;
                socklen_t len = sizeof(clientAddr);
                //有新连接到来
                int peerfd = accept(listenfd, (struct sockaddr*)&clientAddr, &len);
                printf("client %s:%d has connected.\n", 
                       inet_ntoa(clientAddr.sin_addr), 
                       ntohs(clientAddr.sin_port));
                //将peerfd添加到任务队列中
                taskEnqueue(&threadpool.queue, peerfd);
            } else if(fd == exitPipe[0]) {
                //子进程要退出
                //主线程要通知所有的子线程退出
                int howmany = 0;
                read(exitPipe[0], &howmany, sizeof(howmany));

                threadpoolStop(&threadpool);
                printf("threadpool is exiting.\n");
                goto end;
            }
        }
    }
end:
    close(epfd);
    close(listenfd);
    close(exitPipe[0]);
    threadpoolDestroy(&threadpool);
    return 0;
}

